package com.abc.pay.client;

import com.sun.net.ssl.internal.ssl.Provider;
import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;

@Slf4j
public class CertHelper {
    public CertHelper() {
    }

    public static void bindMerchantCertificateByFile(MerchantPara para, ArrayList<String> tCertFileList, ArrayList<String> tCertPasswordList) throws TrxException {
        if (tCertFileList.size() == 0) {
            throw new TrxException("1001", "商户端配置文件中参数设置错误", "商户证书储存目录档名[MerchantCertFile]配置错误！");
        } else if (tCertPasswordList.size() == 0) {
            throw new TrxException("1001", "商户端配置文件中参数设置错误", "商户私钥加密密码[MerchantCertPassword]配置错误！");
        } else if (tCertFileList.size() != tCertPasswordList.size()) {
            throw new TrxException("1001", "商户端配置文件中参数设置错误", "商户证书储存目录档名[MerchantCertFile]或商户私钥加密密码[MerchantCertPassword]配置错误, 数量不匹配！");
        } else {
            int size = tCertFileList.size();
            String errMessage = "";
            ArrayList merchantCertificateList = new ArrayList();
            ArrayList merchantKeyList = new ArrayList();
            for(int i = 0; i < size; ++i) {
                KeyStore tKeyStore = null;
                InputStream tIn = null;
                String tMerchantCertFileName = tCertFileList.get(i);
                String tMerchantCertPassword = tCertPasswordList.get(i);
                Certificate tCert;
                String iMerchantCertificate = null;
                String tAliases = "";
                try {
                    ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
                    if(contextClassLoader != null) {
                        tIn = contextClassLoader.getResourceAsStream(tMerchantCertFileName);
                        if (tIn != null) {
                            tKeyStore = KeyStore.getInstance("PKCS12", (new Provider()).getName());
                            tKeyStore.load(tIn, tMerchantCertPassword.toCharArray());
                            Enumeration iMerchantKey = tKeyStore.aliases();
                            if (iMerchantKey.hasMoreElements()) {
                                tAliases = (String)iMerchantKey.nextElement();
                            }
                            tCert = tKeyStore.getCertificate(tAliases);
                            Base64 tBase64 = new Base64();
                            iMerchantCertificate = tBase64.encode(tCert.getEncoded());
                            merchantCertificateList.add(iMerchantCertificate);
                            X509Certificate tX509Cert = (X509Certificate)tCert;
                            tX509Cert.checkValidity();
                            PrivateKey iMerchantKey1 = (PrivateKey)tKeyStore.getKey(tAliases, tMerchantCertPassword.toCharArray());
                            merchantKeyList.add(iMerchantKey1);
                        }
                    }
                } catch (Exception e) {
                    errMessage = String.format("第%d个证书无法读取，请检查证书路径、文件名以及密码是否正确, %s", i + 1, e);
                    log.error(errMessage);
                    if (tIn != null) {
                        try {
                            tIn.close();
                        } catch (Exception ex) {
                            log.error(Util.getExceptionString(ex));
                        }
                    }
                    log.error(Util.getExceptionString(e));
                    continue;
                }
            }
            para.setMerchantCertificateList(merchantCertificateList);
            para.setMerchantKeyList(merchantKeyList);
            if (!errMessage.equals("")) {
                throw new TrxException("1305", "读取商户证书时失败", errMessage);
            }
        }
    }

    public static void bindMerchantCertificate(MerchantPara para, ArrayList<byte[]> tCertFileList, ArrayList<String> tCertPasswordList) throws TrxException {
        if (tCertFileList.size() == 0) {
            throw new TrxException("1001", "商户端配置文件中参数设置错误", "商户证书储存目录档名[MerchantCertFile]配置错误！");
        } else if (tCertPasswordList.size() == 0) {
            throw new TrxException("1001", "商户端配置文件中参数设置错误", "商户私钥加密密码[MerchantCertPassword]配置错误！");
        } else if (tCertFileList.size() != tCertPasswordList.size()) {
            throw new TrxException("1001", "商户端配置文件中参数设置错误", "商户证书储存目录档名[MerchantCertFile]或商户私钥加密密码[MerchantCertPassword]配置错误！");
        } else {
            int size = tCertFileList.size();
            String errMessage = "";
            ArrayList merchantCertificateList = new ArrayList();
            ArrayList merchantKeyList = new ArrayList();
            for(int i = 0; i < size; ++i) {
                KeyStore tKeyStore;
                ByteArrayInputStream bais = null;
                byte[] tMerchantCertFile = tCertFileList.get(i);
                String tMerchantCertPassword = tCertPasswordList.get(i);
                String tAliases = "";
                Certificate tCert;
                String iMerchantCertificate;
                Enumeration iMerchantKey;
                try {
                    bais = new ByteArrayInputStream(tMerchantCertFile);
                    tKeyStore = KeyStore.getInstance("PKCS12", (new Provider()).getName());
                    tKeyStore.load(bais, tMerchantCertPassword.toCharArray());
                } catch (Exception e) {
                    errMessage = String.format("第%d个证书无法读取，请检查证书路径、文件名以及密码是否正确, %s", i + 1, e);
                    log.error(errMessage);
                    if (bais != null) {
                        try {
                            bais.close();
                        } catch (Exception ex) {
                            log.error(Util.getExceptionString(ex));
                        }
                    }
                    log.error(Util.getExceptionString(e));
                    continue;
                }
                try {
                    iMerchantKey = tKeyStore.aliases();
                    if (iMerchantKey.hasMoreElements()) {
                        tAliases = (String)iMerchantKey.nextElement();
                    }
                    tCert = tKeyStore.getCertificate(tAliases);
                    Base64 tBase64 = new Base64();
                    iMerchantCertificate = tBase64.encode(tCert.getEncoded());
                } catch (Exception e) {
                    errMessage = String.format("第%d个证书格式错误，请检查证书文件格式是否正确，%s", i + 1, e);
                    log.error(errMessage);
                    continue;
                }
                merchantCertificateList.add(iMerchantCertificate);
                try {
                    X509Certificate tX509Cert = (X509Certificate)tCert;
                    tX509Cert.checkValidity();
                } catch (Exception e) {
                    errMessage = String.format("第%d个证书过期，请检查证书有效期, %s", i + 1, e);
                    log.error(errMessage);
                    continue;
                }
                PrivateKey iMerchantKey1;
                try {
                    iMerchantKey1 = (PrivateKey)tKeyStore.getKey(tAliases, tMerchantCertPassword.toCharArray());
                } catch (Exception ex) {
                    errMessage = String.format("第%d个商户私钥无法读取，请检查商户私钥, %s", i + 1, ex);
                    log.error(errMessage);
                    merchantKeyList.add(new Object());
                    continue;
                }
                merchantKeyList.add(iMerchantKey1);
            }
            para.setMerchantCertificateList(merchantCertificateList);
            para.setMerchantKeyList(merchantKeyList);
            if (!errMessage.equals("")) {
                throw new TrxException("1305", "读取商户证书时失败", errMessage);
            }
        }
    }
}
